package tfc_editor.pastrytools;

import easypastry.cast.CastHandler;
import easypastry.core.PastryConnection;
import easypastry.core.PastryKernel;
import easypastry.dht.DHTException;
import easypastry.dht.DHTHandler;
import easypastry.sample.AppCastListener;

/**
 * Classe que gestiona les connexions amb l'easypastry i el DHT Bunshin.
 * @author Ismael Gonzalez Burgos
 *
 */
public class PastryManager
{
    private PastryConnection conn;
    private DHTHandler dht;
    private CastHandler cast;
    private boolean Debuging;

    /**
     * Funcio per a fer un test de la connexio.
     * @throws DHTException Excepcio generada quan hi ha una fallada en la connexio.
     */
    public void testDHT() throws DHTException
    {
        System.out.println("DHT | Inserting : <key1, value1>");
        dht.put("key1", "Clau1");
        System.out.println("DHT | Inserting : <key2, value2>");
        dht.put("key2", "Clau2");
        System.out.println("DHT | Retrieving : <key1>");
        String value1 = (String) dht.get("key1");
        System.out.println("DHT | Current value of <key1> : <"+value1+">");
        if (!(value1.equals("Clau1")))
        {
        	junit.framework.Assert.fail("Error en llegir del DHT la clau key1");
        }
        else
        {
            System.out.println("DHT | Retrieving : <key2>");
        	String value2 = (String) dht.get("key2");
        	System.out.println("DHT | Current value of <key2> : <"+value2+">");
        	if (!(value2.equals("Clau2")))
        	{
        		junit.framework.Assert.fail("Error en llegir del DHT la clau key2");
        	}
        	else
        	{
        		System.out.println("Test DHT Ok");
        	}
        }
    }
    
    /**
     * Funcio per afegir una dupla <Key,Value> a la DHT.
     * @param key Key de la dupla.
     * @param Data Dades o valor a afegir.
     */
    public void AddKeyStringString(String key,String Data)
    {
    	int len=Data.length() >= 10 ? 10 : Data.length();

    	if (Debuging)
    	{
    		System.out.println("DHT | Inserting < <"+key+">, <"+Data.substring(0,len)+"> >");
    	}
    	
   		try
   		{
   			dht.put(key,Data);
   		} catch (Exception e) {}
    }

    /**
     * Funcio per llegir una dada de la DHT.
     * @param key Clau de la dupla a llegir.
     * @return Dada llegida.
     */
    public String GetKeyStringString(String key)
    {
    	String Data="";

   		try
   		{
   			Data = (String)dht.get(key);
   		} catch (Exception e) {}

		if (Debuging)
		{
	   		if (Data!=null)
	   		{
	   			System.out.println("DHT | Reading < <"+key+">, <"+Data+"> >");
	   		}
	   		else
	   		{
	   			System.out.println("DHT | Reading < <"+key+">, <NULL> >");
	   		}
		}

    	return Data;
    }

    /**
     * Funcio que inicialitza la connexio amb easypastry.
     * @param filename Nom del fitxer amb la configuracio d'easypastry.
     * @throws Exception Excepcio llencada si hi ha error.
     */
    public void initKBR(String filename) throws Exception
    {
        PastryKernel.init(filename);
        conn = PastryKernel.getPastryConnection();
    }

    /**
     * Funcio d'inicialitzacio de la DHT.
     * @param context Context.
     * @throws DHTException Execepcio llencada si hi ha error.
     */
    public void initDHT(String context) throws DHTException
    {
        dht = PastryKernel.getDHTHandler(context);
    }

    /**
     * Funcio d'inicialitzacio del cast on ens connectarem.
     * @param group Group al qual volem afegirnos.
     */
    public void initCast(String group)
    {
        cast = PastryKernel.getCastHandler();
        cast.subscribe(group);
        cast.addDeliverListener(group, new AppCastListener());
    }

    /**
     * Funcio que afegeix el node conn a la xarxa easypastry.
     * @throws Exception Excepcio llencada en cas d'error.
     */
    public  void start() throws Exception
    {
        conn.bootNode();
    }

    /**
     * Constructor de la classe.
     * @param args Arguments del programa.
     */
	public PastryManager(String args[])
	{
		try
		{
			initKBR("easypastry-config.xml");
			initDHT("test");
			initCast("p2p://test");
			start();
        } catch(Exception ex)
        {
        	ex.printStackTrace();
        }
	}
}
